#pragma once

#include "TcpServer.hpp"
#include "HttpProtocol.hpp"

using namespace TcpServerModule;

using http_handler_t = std::function<void(HttpRequest&,HttpResponse*)>;  // 我们希望输入一个请求，返回一个应答（输出型参数）

class HttpServer
{
public:
    HttpServer(int port)
        :_tsvr(std::make_unique<TcpServer>(port))
    {}

    // 注册方法，方法名和方法存入哈希表中
    void Register(std::string funcname, http_handler_t handler)
    {
        _route[funcname] = handler;
    }

    // 检查你想要的功能在不在功能map里面
    bool SafeCheck(const std::string &service)
    {
        auto pos = _route.find(service);
        return pos != _route.end();
    }
 
    void Start()
    {
        _tsvr->initServer([this](SockPtr sockfd, InetAddr client){ return this->HandlerHttpRequest(sockfd, client); });
        _tsvr->Loop();
    }

    // 这里就是我们处理http的入口！
    bool HandlerHttpRequest(SockPtr sockfd, InetAddr client)
    {
        LOG(LogLevel::DEBUG) << "HttpServer : Get a new client: " << sockfd->Fd() << " addr info: " << client.Addr();
        string http_request;
        sockfd->Recv(&http_request);
        HttpRequest req;
        req.Deserialization(http_request);
        HttpResponse resp;
        // std::cout << "用户想要：" << req.Uri() << std::endl;
        // req.Print();  // 反序列化后的结果

        // 请求应该被分成两类：1. 请求一般的静态资源  2. 提交参数，携带参数，需要我们进行交互设置，比如/login
        if(req.IsHasArgs())  // 如果有参数要这一步
        {
            // 2. 提交参数，携带参数，需要我们进行交互设置
            std::string service = req.Path();
            if(SafeCheck(service))
                _route[service](req,&resp);
            else resp.Bulid(req);
        }
        else  // 静态资源走这一步
            resp.Bulid(req);
        std::string resp_str;
        resp.Serialization(&resp_str);

        //cout << http_request;  // 字节流的请求

        // http_request 存储的就是client发给我们的请求

        // 现在我们要做的就是读取请求，对请求进行分析处理 --> 文本处理
        // 1. 读取请求的完整性 --- 暂时不做

        // 2. 完整http反序列化，http response 序列化...

        // demo 1:直接返回一个固定的内容
        // std::string status_line = "HTTP/1.1 200 OK" + Sep + Blankline;  // 现在主流HTTP版本号是1.1，如果是正常的访问，就是状态码就是200，状态描述写OK，再加\r\n
        // // 直接返回一个html网页
        // std::string body = "<!DOCTYPE html>\
        //                     <html lang=\"zh-CN\">\
        //                     <head>\
        //                     <meta charset=\"UTF-8\">\
        //                     <title>我喜欢小蛋</title>\
        //                     </head>\
        //                     <body>\
        //                     <p>我喜欢小蛋！</p>\
        //                     </body>\
        //                     </html>";
        // string http_response = status_line + body;
        sockfd->Send(resp_str);


        return true;
    }

private:
    std::unique_ptr<TcpServer> _tsvr;
    std::unordered_map<std::string, http_handler_t> _route;  // 功能路由：存放着要实现的功能
};